import usocket as socket
import ujson


def _urlencode(params):
    """将字典参数编码为URL查询字符串"""
    if not params:
        return ""
    parts = []
    for k, v in params.items():
        parts.append(f"{k}={v}")
    return "?" + "&".join(parts)


class Response:
    def __init__(self, sock):
        self.sock = sock
        self.status_code = None
        self._content = None
        self._closed = False
        self._parse_status()

    def _parse_status(self):
        # 解析状态行获取状态码
        line = self.sock.readline()
        if line:
            parts = line.split()
            if len(parts) >= 3:
                self.status_code = int(parts[1])

        # 跳过响应头
        while True:
            line = self.sock.readline()
            if line in (b'\r\n', b''):
                break

    @property
    def content(self):
        if self._content is None and not self._closed:
            self._content = self.sock.read()
            self.close()  # 读取内容后自动关闭
        return self._content

    def text(self):
        """返回文本格式响应，自动关闭连接"""
        return self.content.decode('utf-8', errors='replace')

    def json(self):
        """返回JSON格式响应，自动关闭连接"""
        try:
            return ujson.loads(self.content)
        except:
            raise ValueError("Invalid JSON response")

    def close(self):
        """关闭连接"""
        if self.sock and not self._closed:
            self.sock.close()
            self.sock = None
            self._closed = True

    # 保留上下文管理器支持
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()


def _request(method, url, params=None, data=None, payload=None, headers=None, timeout=30):
    # 解析URL
    if url.startswith('http://'):
        url = url[7:]
    else:
        raise ValueError("Only HTTP supported")

    # 处理GET参数
    if method == 'GET' and params:
        url += _urlencode(params)

    host, path = (url.split('/', 1) if '/' in url else (url, '/'))
    path = '/' + path if path else '/'

    # 处理端口
    port = 80
    if ':' in host:
        host, port = host.split(':', 1)
        port = int(port)

    # 创建连接
    sock = socket.socket()
    try:
        sock.settimeout(timeout)
        addr = socket.getaddrinfo(host, port)[0][-1]
        sock.connect(addr)

        # 发送请求行
        sock.send(f"{method} {path} HTTP/1.1\r\nHost: {host}\r\n".encode())

        # 发送头部
        headers = headers or {}
        headers.setdefault('Connection', 'close')
        for k, v in headers.items():
            sock.send(f"{k}: {v}\r\n".encode())

        # 处理POST数据
        post_data = None
        if method == 'POST':
            # 优先处理表单数据
            if data is not None:
                post_data = data
                headers.setdefault('Content-Type', 'application/x-www-form-urlencoded')
            # 处理JSON负载
            elif payload is not None:
                post_data = ujson.dumps(payload)
                headers.setdefault('Content-Type', 'application/json')

        # 发送POST数据
        if post_data is not None:
            sock.send(f"Content-Length: {len(post_data)}\r\n\r\n".encode())
            sock.send(post_data.encode() if isinstance(post_data, str) else post_data)
        else:
            sock.send(b'\r\n')

        return Response(sock)
    except:
        sock.close()
        raise


def get(url, params=None, headers=None, timeout=30):
    """发送GET请求，支持params参数"""
    return _request('GET', url, params=params, headers=headers, timeout=timeout)


def post(url, data=None, payload=None, headers=None, timeout=30):
    """发送POST请求，支持表单数据(data)和JSON负载(payload)"""
    return _request('POST', url, data=data, payload=payload, headers=headers, timeout=timeout)


if __name__ == '__main__':
    # GET请求 - 自动关闭
    response = get("http://api.example.com/data", params={"id": 123})
    print("状态码:", response.status_code)
    print("响应内容:", response.json())  # 调用后自动关闭

    # POST表单请求 - 自动关闭
    response = post("http://example.com/login", data="user=test&pass=123")
    print("登录结果:", response.text())  # 调用后自动关闭

    # POST JSON请求 - 自动关闭
    response = post("http://api.example.com/upload", payload={"temp": 25.5})
    print("上传状态:", response.status_code)
    print("返回数据:", response.json())  # 调用后自动关闭